﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace blackhouse.BlackApart.Data {
    public abstract class AdoAdditionalServicesDataAccess : IAdditionalServiceDataAccess {

        #region IAdditionalServiceDataAccess Members

        public abstract int AddServiceToReservation(int reservationId, int serviceId, double price, string clientReview);

        public abstract void AddServiceItemToReservation(int orderId, DateTime date, int quantity, double price);

        public AdditionalServiceData[] GetAvalibleServices(int apartmentGroupId, string language) {
            return this.ReadAdditionalServices(this.GetAvalibleServicesReader(apartmentGroupId, language));
        }

        public AdditionalServiceData[] GetAvalibleServicesForReservation(int forReservationId, string language) {
            return this.ReadAdditionalServices(this.GetAvalibleServicesForReservationReader(forReservationId, language));
        }

        public ReservationAdditionalServiceData GetReservationService(int reservationId, int serviceId) {
            return this.ReadReservationAdditionalServiceData(this.GetReservationServiceReader(reservationId, serviceId));
        }

        public ReservationAdditionalServiceUnitData[] GetServiceItemFromOrder(int orderId) {
            return this.ReadReservationAdditionalServiceUnitsData(this.GetServiceItemFromOrderReader(orderId));
        }

        #endregion

        #region Methods

        private ReservationAdditionalServiceUnitData[] ReadReservationAdditionalServiceUnitsData(IDataReader reader) {
            List<ReservationAdditionalServiceUnitData> data = new List<ReservationAdditionalServiceUnitData>();
            while (reader.Read())
                data.Add(this.ReadReservationAdditionalServiceUnitDataFields(reader));
            reader.Close();
            return data.ToArray();
        }

        private ReservationAdditionalServiceUnitData ReadReservationAdditionalServiceUnitDataFields(IDataReader reader) {
            ReservationAdditionalServiceUnitData data = new ReservationAdditionalServiceUnitData();
            data.Date = Convert.ToDateTime(reader["Date"]);
            data.UnitPrice = Convert.ToDouble(reader["UnitPrice"]);
            data.Quantity = Convert.ToInt32(reader["Quantity"]);
            data.ApartmentId = Convert.ToInt32(reader["Apartment"]);
            return data;
        }

        private AdditionalServiceData[] ReadAdditionalServices(IDataReader reader) {
            List<AdditionalServiceData> data = new List<AdditionalServiceData>();
            while (reader.Read())
                data.Add(this.ReadAdditionalServiceFields(reader));
            reader.Close();
            return data.ToArray();
        }

        private AdditionalServiceData ReadAdditionalServiceFields(IDataReader reader) {
            AdditionalServiceData data = new AdditionalServiceData();
            data.ServiceId = Convert.ToInt32(reader["ServiceId"]);
            data.ServiceKey = Convert.ToString(reader["ServiceKey"]);
            data.ServiceName = Convert.ToString(reader["ServiceName"]);
            data.Description = Convert.ToString(reader["Description"]);
            data.ApartmentDescription = Convert.ToString(reader["ApartmentDescription"]);
            data.ServiceDate = Convert.ToBoolean(reader["ServiceDate"]);
            data.ServiceRoom = Convert.ToBoolean(reader["ServiceRoom"]);
            data.ServiceQuantity = Convert.ToBoolean(reader["ServiceQuantity"]);
            data.ServiceTime = Convert.ToString(reader["ServiceTime"]);
            data.UnitPrice = Convert.ToDouble(reader["UnitPrice"]);
            if (!reader.IsDBNull(reader.GetOrdinal("PriceOnDemand")))
                data.PriceOnDemand = Convert.ToDouble(reader["PriceOnDemand"]);
            if (!reader.IsDBNull(reader.GetOrdinal("ReviewTitle")))
                data.ReviewTitle = Convert.ToString(reader["ReviewTitle"]);
            data.DefaultQuantity = Convert.ToInt32(reader["DefaultQuantity"]);
            data.RemoveQuantityLimit = Convert.ToBoolean(reader["RemoveQuantityLimit"]);
            return data;
        }

        private ReservationAdditionalServiceData ReadReservationAdditionalServiceData(IDataReader reader) {
            ReservationAdditionalServiceData data = default(ReservationAdditionalServiceData);
            if (reader.Read())
                data = this.ReadReservationAdditionalServiceDataFields(reader);
            reader.Close();
            return data;
        }

        private ReservationAdditionalServiceData ReadReservationAdditionalServiceDataFields(IDataReader reader) {
            ReservationAdditionalServiceData data = new ReservationAdditionalServiceData();
            data.OrderId = Convert.ToInt32(reader["OrderId"]);
            if (!reader.IsDBNull(reader.GetOrdinal("ClientReview")))
                data.ClientReview = Convert.ToString(reader["ClientReview"]);
            return data;
        }

        #endregion

        #region Abstracts

        protected abstract IDataReader GetAvalibleServicesReader(int apartmentGroupId, string language);
        protected abstract IDataReader GetAvalibleServicesForReservationReader(int forReservationId, string language);
        protected abstract IDataReader GetReservationServiceReader(int reservationId, int serviceId);
        protected abstract IDataReader GetServiceItemFromOrderReader(int orderId);

        #endregion
    }
}
